﻿#include "thread.h"
#include <QSemaphore>
#include "camera.h"

int curbuf=1;

bool sendflag=false;

QSemaphore closestate;
QSemaphore closeflag;

//unsigned char *bufferForRGB_1=NULL;         //RGB缓存区1
//unsigned char *bufferForRGB_2=NULL;         //RGB缓存区2

QSemaphore emptybuff(2);
QSemaphore fullbuff;

SapLocation *m_loc=NULL;
SapAcqDevice *m_acq=NULL;
SapBuffer *m_buffer=NULL;
SapColorConversion *m_conv=NULL;
SapAcqDeviceToBuf *m_trans=NULL;

cv::Mat mat_1;
cv::Mat mat_2;

cv::Mat mat_learn;

QThreadRead::QThreadRead(QObject *parent) : QThread(parent)
{
    m_stop=false;
    m_mutex=new QMutex;
}

QThreadDeal::QThreadDeal(QObject *parent) : QThread(parent)
{
    m_stop=false;
    m_mutex=new QMutex;
}

QThreadLearn::QThreadLearn(QObject *parent) : QThread(parent)
{

}

ReadForLearn::ReadForLearn(QObject *parent) : QThread(parent)
{
    m_stop=false;
    m_mutex=new QMutex;
}

QThreadDisplay::QThreadDisplay(QObject *parent) : QThread(parent)
{

}

//-------------------------------------------------------------------------------------------------------------

void onImageDataCallback(SapXferCallbackInfo *pInfo)
{
   // Display the last transferred frame

    qDebug()<<"grab thread:"<<GetCurrentThreadId();

    int width = m_buffer->GetWidth();
    int height =m_buffer->GetHeight();
    m_conv->Convert();



    SapBuffer *conv_buff=m_conv->GetOutputBuffer();
    SapBuffer* a=new SapBuffer(1,2048,9400,SapFormatMono8,SapBuffer::TypeScatterGather);
    unsigned char pdata_rgb;
    void* pDataAddr_rgb=&pdata_rgb;
    conv_buff->GetAddress(&pDataAddr_rgb);
    cv::Mat img(height,width,CV_8UC3,pDataAddr_rgb);

    emptybuff.acquire();
    if(curbuf==1)
    {
        mat_1 =img;
        conv_buff->ReleaseAddress(pDataAddr_rgb);
        curbuf=2;
        fullbuff.release();      
    }
    else
    {
        mat_2 =img;
        conv_buff->ReleaseAddress(pDataAddr_rgb);
        curbuf=1;
        fullbuff.release();

    }


    //m_buffer->Clear();
    //view->Destroy();

    qDebug()<<"-----------------------"<<emptybuff.available()<<";"<<fullbuff.available();
    closeflag.release();
}





void onImageForLearnCallback(SapXferCallbackInfo *pInfo)
{
    // Display the last transferred frame
    qDebug()<<"grab thread:"<<GetCurrentThreadId();

    int width = m_buffer->GetWidth();
    int height =m_buffer->GetHeight();
    m_conv->Convert();

    SapBuffer *conv_buff=m_conv->GetOutputBuffer();

    unsigned char pdata_rgb;
    void* pDataAddr_rgb=&pdata_rgb;
    conv_buff->GetAddress(&pDataAddr_rgb);


    cv::Mat img(height,width,CV_8UC3,pDataAddr_rgb);

    char filepath[20];
    strcpy(filepath,dirpath);
    char num[10];
    sprintf(num,"%d.bmp",index);
    index++;
    strcat(filepath,num);
    cv::imwrite(filepath,img);
    conv_buff->ReleaseAddress(pDataAddr_rgb);
    qDebug()<<height;

    mat_learn=img;
    sendflag=true;
    closestate.release();

}
void QThreadRead::run()
{
    qDebug()<<QThread::currentThreadId()<<"______read thread run______";
    m_stop=false;

    int n=emptybuff.available();
    if(n<2)
    {
        emptybuff.release(2-n);
    }

    if(!openCamera())
    {
        return ;
    }
    //getCameraFeature();
    m_conv->Enable(TRUE,FALSE);
    m_conv->SetAlign(SapColorConversion::AlignRGBG);
    m_conv->SetMethod(SapColorConversion::Method7);
    m_conv->SetOutputFormat(SapFormatRGB888);
    m_trans->SetAutoEmpty(TRUE);
    m_trans->Grab();

    while (1)
    {
        closeflag.acquire();

        msleep(450);
        m_trans->Freeze();
        m_trans->Wait(100);
        closeCamera();
        openCamera();
        m_conv->Enable(TRUE,FALSE);
        m_conv->SetAlign(SapColorConversion::AlignRGBG);
        m_conv->SetMethod(SapColorConversion::Method7);
        m_conv->SetOutputFormat(SapFormatRGB888);
        m_trans->Grab();

//        //1
//        m_acq->Close();
//        m_acq->Open();

//        //2
//        m_trans->Freeze();
//        m_trans->Wait(100);
//        m_trans->Grab();

//        //3
//        m_trans->Disconnect();
//        m_trans->Connect();

    }
    m_trans->Freeze();
    m_trans->Wait(5000);
    qDebug()<<"______read thread quit______";
    closeCamera();
}


void QThreadRead::exitThread()
{
    m_mutex->lock();
    m_stop = true;
    m_mutex->unlock();
}


//---------------------------------------------------------------------------------------------------------------

void QThreadDeal::run()
{
    class PyThreadStateLock PyThreadLock;
    qDebug()<<QThread::currentThreadId()<<"_____deal thread run______";
    qDebug()<<"1.available resource"<<emptybuff.available()<<","<<fullbuff.available();
    int n=fullbuff.available();
    if(n>0)
    {
        fullbuff.acquire(n);
    }

    if(PFun2)
    {
        qDebug()<<"python init success";
    }
    sleep(1);

    while (1)
    {
        m_mutex->lock();
        if(m_stop)
        {
            break;
        }
        m_mutex->unlock();

        fullbuff.acquire();

        if(curbuf==1)
        {

            emit sendimage(mat_2);

            npy_intp Dims[3] = {mat_2.rows,mat_2.cols,mat_2.channels()}; //给定维度信息
            qDebug()<<mat_2.rows<<mat_2.cols<<mat_2.channels();
            PyObject* pReturn=call_python_file(Dims,mat_2.data);
            deal_ret_from_python(pReturn);

            emptybuff.release();
            qDebug()<<"-----buffer 2 has been freed-----";
        }
        else
        {
            emit sendimage(mat_1);

            npy_intp Dims[3] = {mat_1.rows,mat_1.cols,mat_1.channels()}; //给定维度信息
            qDebug()<<mat_1.rows<<mat_1.cols<<mat_1.channels();
            PyObject* pReturn=call_python_file(Dims,mat_1.data);
            deal_ret_from_python(pReturn);

            emptybuff.release();
            qDebug()<<"-----buffer 1 has been freed-----";
        }
         qDebug()<<"-----------------------"<<emptybuff.available()<<";"<<fullbuff.available();
    }
    m_mutex->unlock();
    qDebug()<<"______deal thread quit______";
}

//PyObject* QThreadDeal::initpythonmodule()
//{
//    Py_Initialize();
//    if (!Py_IsInitialized())
//    {
//        qDebug() << "Python init failed";
//    }

//    import_array();

//    PyImport_ImportModule("sys");
//    PyRun_SimpleString("import sys"); // 执行 python 中的短语句
//    PyRun_SimpleString("sys.path.append('C:/Users/dk/Desktop/classify/')");

//    pModule = PyImport_ImportModule("predict");//Python文件名
//    if (!pModule)
//    {
//        qDebug() << "import moudle failed";
//        return NULL;
//    }

//    pDict = PyModule_GetDict(pModule);
//    if(!pDict)
//    {
//        qDebug()<<"import function failed";
//        return NULL;
//    }

//    PyObject* pClass=PyDict_GetItemString(pDict,"Classification");
//    if(!pClass)
//    {
//        qDebug()<<"get class failed";
//        return NULL;
//    }

//    PyObject* pObject=PyInstanceMethod_New(pClass);
//    if(!pObject)
//    {
//        qDebug()<<"get init function failed";
//        return NULL;
//    }

//    PyObject* pInstance=PyObject_CallObject(pObject,NULL);
//    if(!pInstance)
//    {
//        qDebug()<<"instance failed";
//        return NULL;
//    }

//    return pInstance;
//}


PyObject* QThreadDeal::call_python_file(npy_intp* diminfo,unsigned char* buff)
{
    import_array();      //此处不调用PyArray_SimpleNewFromData会发送错误
    PyObject *PyArray = PyArray_SimpleNewFromData(3, diminfo, NPY_UBYTE, buff);

    PyObject *ArgArray = PyTuple_New(1);                    //构造参数
    PyTuple_SetItem(ArgArray, 0, PyArray);
    if(!PFun2)
    {
        qDebug()<<"pointer of class is NULL!";
    }
    PyObject* pReturn=PyObject_CallMethod(PFun2,"prediction","O",ArgArray);

    return pReturn;
}

void QThreadDeal::deal_ret_from_python(PyObject* ret)
{
    if(!ret)
    {
        qDebug()<<"return failed";
    }

    int res = 0;
    PyArg_Parse(ret, "i", &res);//转换返回类型
    qDebug() << "res:" << res ;//输出结果
    emit sendRes(res);

    return ;
}

void QThreadDeal::exitThread()
{
    m_mutex->lock();
    m_stop = true;
    m_mutex->unlock();
}

void ReadForLearn::run()
{
    if(!openCameraForLearn())
    {
        return ;
    }
    m_conv->Enable(TRUE,FALSE);
    m_conv->SetAlign(SapColorConversion::AlignRGBG);
    m_conv->SetMethod(SapColorConversion::Method7);
    m_conv->SetOutputFormat(SapFormatRGB888);

    m_trans->Grab();
    while (1)
    {
        closestate.acquire();

        msleep(450);
        m_trans->Freeze();
        m_trans->Wait(100);
        closeCamera();
        openCameraForLearn();
        m_conv->Enable(TRUE,FALSE);
        m_conv->SetAlign(SapColorConversion::AlignRGBG);
        m_conv->SetMethod(SapColorConversion::Method7);
        m_conv->SetOutputFormat(SapFormatRGB888);
        m_trans->Grab();



    }
    m_trans->Freeze();
    m_trans->Wait(5000);
    qDebug()<<"______read thread quit______";
    closeCamera();
    m_mutex->unlock();
}


void ReadForLearn::exitThread()
{
    m_mutex->lock();
    m_stop = true;
    m_mutex->unlock();
}

void QThreadLearn::run()
{
    if(PFun1)
    {
        qDebug()<<"training module init success";
    }

    train_model();
    emit learnCompelete();
    exit(0);
}

//PyObject* QThreadLearn::initpythonmodule()
//{
//    Py_Initialize();
//    if (!Py_IsInitialized())
//    {
//        qDebug() << "Python init failed";
//    }

//    PyImport_ImportModule("sys");
//    PyRun_SimpleString("import sys"); // 执行 python 中的短语句
//    PyRun_SimpleString("sys.path.append('C:/Users/dk/Desktop/classify/')");

//    PyObject *pModule;
//    pModule = PyImport_ImportModule("training");//Python文件名
//    if (!pModule)
//    {
//        qDebug() << "import moudle failed";
//        return NULL;
//    }

//    PyObject* pDict = PyModule_GetDict(pModule);
//    if(!pDict)
//    {
//        qDebug()<<"import function failed";
//        return NULL;
//    }

//    PyObject* pClass=PyDict_GetItemString(pDict,"Classification");
//    if(!pClass)
//    {
//        qDebug()<<"get class failed";
//        return NULL;
//    }

//    PyObject* pObject=PyInstanceMethod_New(pClass);
//    if(!pObject)
//    {
//        qDebug()<<"get init function failed";
//        return NULL;
//    }

//    PyObject* pInstance=PyObject_CallObject(pObject,NULL);
//    if(!pInstance)
//    {
//        qDebug()<<"instance failed";
//        return NULL;
//    }

//    return pInstance;
//}


void QThreadLearn::train_model()
{
    class PyThreadStateLock PyThreadLock;
    PyObject* pReturn=PyObject_CallMethod(PFun1,"training_data",NULL);
    if(!pReturn)
    {
        qDebug()<<"return failed";
    }

    int ret = 0;
    PyArg_Parse(pReturn, "i", &ret);//转换返回类型
    qDebug() << "ret:" << ret ;

    qDebug()<<"learn compelete";
    emit learnCompelete();
}

void QThreadDisplay::run()
{
    while(1)
    {
        if(sendflag==true)
        {
            emit sendimage2(mat_learn);
            qDebug()<<"send it";
            sendflag=false;
        }
    }
}
